package lion.bugrambo.execution;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;

import lion.bugrambo.model.Project;
import lion.bugrambo.model.ProjectModel;
import lion.dev.lang.Lang;
import lion.dev.lang.MapJ;
import lion.dev.web.Validator;
import lion.dev.web.paging.PagedVo;
import lion.framework.core.db.DB;
import lion.framework.core.db.DataTable;
import lion.framework.core.db.SessionFactory;
import lion.framework.core.db.paging.SQLPagingFactory;
import lion.framework.core.web.anno.Namespace;
import lion.framework.core.web.anno.Path;
import lion.framework.core.web.anno.Result;
import lion.framework.core.web.anno.View;
import lion.framework.core.web.request.Request;
import lion.framework.core.web.views.ResultType;
import lion.web.platform.model.User;
import lion.web.platform.priv.user.LoginUser;

/**
 * 项目管理
 * 
 * @author lion
 * @email hl_0074@sina.com
 * @date l2014年12月2日
 */
@Namespace("#{admin}/br")
public class ProjectExecution {

	@Path("/project")
	@Result(@View("/WEB-INF/template/bugrambo/project/index.jsp"))
	public String index() {

		return "success";
	}

	@Path("project/list")
	@Result(@View(type = ResultType.JSON))
	public String list(Request request) {

		int page = request.getInt("page", 1);
		int size = request.getInt("size", 30);

		PagedVo<Project> pagedVo = new PagedVo<>(Project.count());
		pagedVo.getPaging().setPageNumber(page);
		pagedVo.getPaging().setPageSize(size);

		pagedVo.setVos(Project.list(pagedVo.getPaging().getStartRowNumber(), pagedVo.getPaging().getPageSize()));

		String sql = "select p.*,(select realName from User u where u.id = p.owner) ownerName from Project p order by id desc";

		DB db = SessionFactory.getCurrentDB();
		DataTable dt = db.query(SQLPagingFactory.paging(db.getType(), sql, pagedVo.getPaging().getStartRowNumber(), pagedVo.getPaging().getPageSize()));

		request.addModel("vos", dt.getRows());
		request.addModel("paging", pagedVo.getPaging());

		return "success";
	}

	@Path("project/projects")
	@Result(@View(type = ResultType.JSON))
	public String listProjects(Request request) {

		if (LoginUser.current().hasPriv("BR.PROJ")) {
			request.addModel("data", Project.list(-1));
		} else {
			request.addModel("data",
					Project.list(-1, "where id in (select 1 from ProjectUser pu where pu.projectId=id and pu.userId=" + LoginUser.current().getUser().getId() + ")"));
		}

		return "success";
	}

	@Path("/project/save")
	@Result(@View(type = ResultType.JSON))
	public String save(Request request) {

		// project info
		Project project = Project.create(request);

		if (SessionFactory.getCurrentDB().queryTrue("select 1 from Project where name=:name", request)) {
			request.addError("msg", "名称已存在,请更换");
			return "success";
		}

		project.setCreateTime(new Date());
		project.setCreator(LoginUser.current().getUser().getId());
		project.save();

		int[] ids = Validator.toIntArray(request.getString("projectUsers"));
		if (ids.length == 0) { return "success"; }
		DB db = SessionFactory.getCurrentDB();
		List<String> sqls = new ArrayList<>();
		for (int id : ids) {
			sqls.add("insert into ProjectUser(projectId,userId) values(" + project.getId() + "," + id + ")");
		}
		db.updateBatch(sqls.toArray(new String[0]));

		return "success";
	}

	@Path("/project/delete")
	public void delete(Request request) {

		if (!LoginUser.current().hasPriv("BR.PROJ")) { return; }

		int[] ids = Validator.toIntArray(request.getString("ids"));
		System.out.println(request.toJSON());
		if (ids.length == 0) { return; }
		for (int id : ids) {
			deleteProject(id);
		}
	}

	private void deleteProject(int id) {

		// 删除项目
		// 删除模块
		// 删除项目成员
		// 删除项目bug
		// 删除需求

		String[] sqls = new String[] { "delete from Project where id=" + id, "delete from ProjectUser where projectId=" + id, "delete from ProjectModel where projectId=" + id,
				"delete from Requirement where projectId=" + id, "delete from Bug where projectId=" + id };
		SessionFactory.getCurrentDB().updateBatch(sqls);

	}

	@Path("/project/update")
	public void update(Request request) {

		// update project
		Project project = Project.load(request.getInt("id"));
		if (project == null) { return; }

		project.setName(request.getString("name"));
		project.setOwner(request.getInt("owner"));
		project.update();

		// update project users
		int[] ids = Validator.toIntArray(request.getString("projectUsers"));
		if (ids.length == 0) { return; }
		DB db = SessionFactory.getCurrentDB();
		List<String> sqls = new ArrayList<>();
		sqls.add("delete from ProjectUser where projectId=" + project.getId());

		for (int id : ids) {
			sqls.add("insert into ProjectUser(projectId,userId) values(" + project.getId() + "," + id + ")");
		}
		db.updateBatch(sqls.toArray(new String[0]));
	}

	@Path("/project/edit")
	@Result(@View("/WEB-INF/template/bugrambo/project/edit.jsp"))
	public String edit(Request request) {

		int id = request.getInt("projectId");
		if (id < 0) { return "success"; }
		Project project = Project.load(id);
		if (project == null) { return "success"; }
		request.addModel("project", project);

		User owner = User.load(project.getOwner());
		request.addModel("owner", owner);

		return "success";
	}

	@Path("/project/users")
	@Result(@View(type = ResultType.JSON))
	public String projectUsers(Request request) {

		int page = request.getInt("page", 1);
		int size = request.getInt("size", 20);
		int projectId = request.getInt("projectId");
		if (projectId < 0) { return "success"; }

		DB db = SessionFactory.getCurrentDB();
		PagedVo<MapJ> pagedVo = new PagedVo<>(db.queryInt(
				"select count(*) from User u,Organization o where u.orgId=o.id and exists (select 1 from ProjectUser pu where pu.userId=u.id and pu.projectId=?)", projectId));

		pagedVo.getPaging().setPageNumber(page);
		pagedVo.getPaging().setPageSize(size);

		String sql = SQLPagingFactory.paging(db.getType(),
				"select u.id,u.realName,u.email,o.name orgName from User u,Organization o where u.orgId=o.id and exists (select 1 from ProjectUser pu where pu.userId=u.id and pu.projectId=?)",
				pagedVo.getPaging().getStartRowNumber(), pagedVo.getPaging().getPageSize());

		pagedVo.setVos(db.query(sql, projectId).getRows());

		request.addModel("vos", pagedVo.getVos());
		request.addModel("paging", pagedVo.getPaging());

		return "success";
	}

	@Path("/project/users/add")
	public void addUser(Request request) {

		int projectId = request.getInt("projectId");
		int[] ids = Validator.toIntArray(request.getString("ids"));

		if (projectId < 0) { return; }

		DB db = SessionFactory.getCurrentDB();
		List<Integer> oldIds = db.queryCol("select userId from ProjectUser where projectId=?", projectId);
		List<String> sqls = new ArrayList<>();
		for (int id : ids) {
			if (oldIds.contains(id)) {
				continue;
			}
			sqls.add("insert into ProjectUser(projectId,userId) values(" + projectId + "," + id + ")");
		}
		if (!sqls.isEmpty()) {
			db.updateBatch(sqls.toArray(new String[0]));
		}
	}

	@Path("/project/users/delete")
	public void deleteUser(Request request) {

		int projectId = request.getInt("projectId");
		int[] ids = Validator.toIntArray(request.getString("ids"));

		if (projectId < 0) { return; }

		SessionFactory.getCurrentDB().update("delete from ProjectUser where projectId=? and userId in(" + Lang.join(ids) + ")", projectId);
	}

	@Path("/project/modules/list")
	@Result(@View(type = ResultType.JSON))
	public String modules(Request request) {

		int projectId = request.getInt("projectId");
		if (projectId > 0) {
			request.addModel("data", ProjectModel.list(-1, "where projectId=" + projectId));
		}
		return "success";
	}

	@Path("/project/modules/edit")
	@Result(@View("/WEB-INF/template/bugrambo/project/editmodel.jsp"))
	public String editModel(Request request) {

		int projectId = request.getInt("projectId");
		int pid = request.getInt("pid");
		ProjectModel pm = ProjectModel.load(request.getInt("id"));
		request.addModel("model", pm);
		if (pm != null) {
			pid = pm.getPid();
			projectId = pm.getProjectId();

			request.addModel("owner", User.load(pm.getManager()));

		}
		request.addModel("projectId", projectId);

		request.addModel("pmodel", ProjectModel.load(pid));

		return "success";
	}

	@Path("/project/modules/save")
	public void saveModel(Request request) {

		ProjectModel pm = ProjectModel.create(request);
		pm.setCreateTime(new Date());
		pm.setCreator(LoginUser.current().getUser().getId());

		pm.save();

		ProjectModel parent = ProjectModel.load(pm.getPid());
		String path = "";
		if (parent != null) {
			path = parent.getPath();
		}
		if (StringUtils.isBlank(path)) {
			path = "";
		}
		pm.setPath(path + "/" + pm.getId());
		pm.update();

	}

	@Path("/project/modules/update")
	public void updateModel(Request request) {

		ProjectModel pm = ProjectModel.load(request.getInt("id"));
		if (pm == null) { return; }
		pm.setName(request.getString("name"));
		pm.setManager(request.getInt("manager"));

		pm.update();
	}

	@Path("/project/modules/delete")
	public void deleteModel(Request request) {

		if (!LoginUser.current().hasPriv("BR.PROJ.Model")) { return; }

		ProjectModel pm = ProjectModel.load(request.getInt("id"));
		if (pm == null) { return; }
		pm.delete();
		SessionFactory.getCurrentDB().update("delete from ProjectModel where path like '" + StringEscapeUtils.escapeSql(pm.getPath()) + "/%'");

	}
}
